//
//  IMTCANManager.m
//  ROCOMO
//
//  Created by Kyle Sun on 5/13/16.
//  Copyright © 2016 ROCOMO. All rights reserved.
//

#import "IMTCANManager.h"

#import "IMTCarManager.h"
#import "IMTCANMessageCoder.h"
#import "IMTCANMessageAnalyser.h"
#import "IMTCANMessageFactory.h"
#import "IMTCANR0MessageCoder.h"
#import "IM_NewMessageCoder.h"
#import "IM_NewMessageFactory.h"
#import "IMFunction.h"

const NSInteger kIMTCANMaxPacketSize = 160;
NSString * const IMTCANManagerErrorDomain = @"IMTCANManagerErrorDomain";

@interface IMTCANManager()

@property (nonatomic, strong) IMTCANMessageCoder *messageCoder;
@property (nonatomic, strong) IM_NewMessageCoder *newMessageCoder;
@property (nonatomic, strong) IMTCANMessageAnalyser *messageAnalyser;
@property (nonatomic, strong) NSMutableArray *messageList;
@property (nonatomic, strong) NSMutableArray *blockList;
@property (nonatomic, strong) dispatch_queue_t messageQueue;
@property (nonatomic, strong) IMTCANMessage *sendingMessage;
@property (nonatomic,   copy) IMTCANMessageCompletionBlock sendingBlock;
@property (nonatomic, strong) NSTimer *timer;
@property (nonatomic, assign) CGFloat timeOut;

@property (nonatomic , strong) NSMutableData *hasData; // e系列不完整数据


@end

@implementation IMTCANManager

-(NSMutableData *)hasData {
    if (!_hasData) {
        _hasData = [NSMutableData data];
    }
    return _hasData;
}

+ (IMTCANManager *)sharedInstance {
    
    static IMTCANManager *_sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[IMTCANManager alloc] init];
    });
    return _sharedInstance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        
        /// 创建蓝牙管理工具并接收数据
        [KSBLEManager sharedManager].receiveDataBlock = ^(NSData *bledata) {
                        
            if (self.getCarModelType == IMCarTypeCodeR0) {
                uint8_t packdataLength;
                uint8_t first;
                uint8_t next;
                [bledata getBytes:&first range:NSMakeRange(0, 1)];
                [bledata getBytes:&next range:NSMakeRange(1, 1)];
                [bledata getBytes:&packdataLength range:NSMakeRange(2, 1)];
                if (first == 0x55 && next == 0xab) {
                    if (packdataLength > bledata.length - 7) {
                        self.hasData = [NSMutableData dataWithData:bledata];
                        return;
                    }else {
                        self.hasData = [NSMutableData dataWithData:bledata];
                    }
                }else {
                    [self.hasData appendData:bledata];
                }
                
                [IMTCANR0MessageCoder IAPUnpackWithData:self.hasData resultBlock:^(NSData *data, unsigned char cmdID, unsigned char otherID, unsigned char dev) {
                    self.hasData = nil;
                    if (data) {
                        IMTCANMessage *message = [[IMTCANMessage alloc] initWithCmd:cmdID otherID:otherID dev:dev extra:data];
                        NSLog(@"🌹解包R0数据 -- 数据段：%@ ------ 功能码：%d ------ 附加功能码：%d ----- 报文接受设备：%d key:%@",data,cmdID,otherID,dev,message.key);
                        if (message != nil) {
                            NSError *error = [NSError errorWithDomain:IMTCANManagerErrorDomain code:2 userInfo:@{NSLocalizedDescriptionKey: @"操作失败"}];
                            if (cmdID == 7 || cmdID == 8 || cmdID == 9) {
                                if (otherID == 0) {
                                    [self dispatchMessage:message error:nil];
                                }else {
                                    [self dispatchMessage:message error:error];
                                }
                            }else if (cmdID == 10) {
                                if (otherID == 1) {
                                    [self dispatchMessage:message error:nil];
                                }else {
                                    [self dispatchMessage:message error:error];
                                }
                            }else {
                                [self dispatchMessage:message error:nil];
                            }
                        }
                    }
                }];
            }else if (self.getCarModelType == IMCarTypeCodeOld){
                NSData *messageData = [self.messageAnalyser messageDataFromData:bledata];
                NSLog(@"🌹解包旧协议数据 -- 数据段：%@",messageData);
                if (messageData) {
                    IMTCANMessage *message = [self.messageCoder messageFromData:messageData];
                    if (message != nil) {
                        [self dispatchMessage:message error:nil];
                    }
                }
            }else if((self.getCarModelType == IMCarTypeCodeL9)||(self.getCarModelType == IMCarTypeCodeVX)){
                if (bledata) {
                    IMTCANMessage *message =[self.newMessageCoder transformMessageFromData:bledata];
                    NSLog(@"🌹解包VX、L9数据 -- 数据段：%@ -- key:%@ == length：%hhu --cmd：%u -- datatype：%u",bledata,message.key,message.newBody.length,message.DedicatedData.cmd,message.newBody.format.dataType);
                    if (message != nil) {
                        [self dispatchMessage:message error:nil];
                    }
                }
            }

        };
    }
    
    return self;
}

///  判断协议车型 （旧协议，R0协议，新协议）
- (IMCarTypeCode)getCarModelType
{
    IMTCarManager *manager = [IMTCarManager sharedCarManager];
    return manager.carModelType;
}

/// 发送消息
- (void)sendMessage:(IMTCANMessage *)message completion:(IMTCANMessageCompletionBlock)completion {
    self.timeOut = 1.0;
    [self enqueueMessage:message CompletionBlock:completion];
}

/// 发送消息
- (void)sendMessage:(IMTCANMessage *)message withTimeOut:(CGFloat)timeOut completion:(IMTCANMessageCompletionBlock)completion {
    self.timeOut = timeOut;
    [self enqueueMessage:message CompletionBlock:completion];
}

/// 发送消息无需入列
- (void)sendMessage:(IMTCANMessage *)message {
    if (self.getCarModelType == IMCarTypeCodeR0) {
        [KSBLEManager.sharedManager sendData:message.extra];
    } else if (self.getCarModelType == IMCarTypeCodeOld){
        NSData *data = [self.messageCoder dataFromMessage:message];
        [KSBLEManager.sharedManager sendData:data];
    }else if ((self.getCarModelType == IMCarTypeCodeL9)|(self.getCarModelType == IMCarTypeCodeVX)){
        NSData *data = [self.newMessageCoder transformDataFromMessage:message];
        [KSBLEManager.sharedManager sendData:data];
    }
}

/// 添加车子主动发送数据的处理
- (void)addReceiveDataFromCarWithCompletionBlock:(IMTCANMessageCompletionBlock)block forKey:(NSString *)key {
    self.carDataBlock = block;
    self.carDataKey = key;
}

/// 加入block
- (void)addCompletionBlock:(IMTCANMessageCompletionBlock)block forKey:(NSString *)key {
    if (block) {
        [self.blockList addObject:@{key:block}];
    }
}
/// 移除消息回调block -- 外部有单独使用该方法
- (void)removeCompletionBlockForKey:(NSString *)key {
    
}

/// 清除消息 --- 暂时不用外部处理
- (void)clearMessages {
    NSLog(@"-------------- 清除消息队列 ");
    if (self.timer.isValid) {
        [self.timer invalidate];
        self.timer = nil;
    }
    @synchronized(self) {
        [self.blockList removeAllObjects];
        [self.messageList removeAllObjects];
        self.sendingMessage = nil;
        self.sendingBlock = nil;
    }
}

/// 入列 ------- 异步串行
- (void)enqueueMessage:(IMTCANMessage *)message CompletionBlock:(IMTCANMessageCompletionBlock)block{
    if (self.messageQueue == nil) {
        self.messageQueue = dispatch_queue_create("com.imscv.IMTCANManager.messageQueue", DISPATCH_QUEUE_SERIAL);
    }
    /// 消息队列延时20毫秒执行  dispatch_async(self.messageQueue, ^{ });
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), self.messageQueue, ^{
        NSLog(@"=======================入列🍰🍰🍰%@",message.key);
        [self addCompletionBlock:block forKey:message.key]; // 加入block
        [self.messageList addObject:message];
        [self checkMessageQueue];
    });

}

- (void)checkMessageQueue {
    if (KSBLEManager.sharedManager.state != KSBLEManagerStateSubscribed) {
        [self clearMessages];
        return;
    }
    
    if (self.messageList.count > 0 && self.blockList.count > 0) {
        if (self.sendingMessage && self.sendingBlock) {
            return;
        }
        IMTCANMessage *message = [self.messageList firstObject];
        self.sendingMessage = message;
        
        NSDictionary *blockDic = self.blockList.firstObject;
        IMTCANMessageCompletionBlock block = blockDic.allValues.firstObject;
        self.sendingBlock = block;

        if (self.getCarModelType == IMCarTypeCodeR0) {
            [KSBLEManager.sharedManager sendData:message.extra];
            if (message.body.cid == 7) {
                self.timeOut = 3.5;
            }
        } else if (self.getCarModelType == IMCarTypeCodeOld){
            NSData *data = [self.messageCoder dataFromMessage:message];
            [KSBLEManager.sharedManager sendData:data];
        }else if ((self.getCarModelType == IMCarTypeCodeL9)|(self.getCarModelType == IMCarTypeCodeVX)){
            NSData *data = [self.newMessageCoder transformDataFromMessage:message];
            [KSBLEManager.sharedManager sendData:data];
        }
        
        // 超时处理: 使用主线程Runloop来驱动timer
        dispatch_async(dispatch_get_main_queue(), ^{
            if (self.timer.isValid) {
                [self.timer invalidate];
                self.timer = nil;
            }
            self.timer = [NSTimer scheduledTimerWithTimeInterval:self.timeOut target:self selector:@selector(timerFired:) userInfo:nil repeats:NO];
        });
    }
}

- (void)timerFired:(NSTimer *)timer {
    dispatch_async(dispatch_get_main_queue(), ^{
        // 如果还处在发送状态，说明没有收到回应
        if (self.sendingMessage && self.messageList.count > 0) {
            IMTCANMessage *message = self.sendingMessage;
            NSString *errorDescription = [NSString stringWithFormat:@"CANMessage timeout error. [%@]", message.key];
            NSError *error = [NSError errorWithDomain:IMTCANManagerErrorDomain
                                                 code:1
                                             userInfo:@{NSLocalizedDescriptionKey: errorDescription}];
            [self dispatchMessage:message error:error];
        }
    });
}

- (void)dispatchMessage:(IMTCANMessage *)message error:(NSError *)error {

    if ([message.key isEqualToString:@"f060101"]) { // v10快速连接不处理
        return;
    }
    
    if ([self.sendingMessage.key isEqualToString:message.key]) {
        IMTCANMessageCompletionBlock block = self.sendingBlock;
        NSLog(@"🐯开启回调 == message.key:%@ == block:%@ == error:%@ == self.sendingMessage.key:%@ ------ blocklist:%lu ====== messagelist:%lu",message.key,block,error,self.sendingMessage.key,(unsigned long)self.blockList.count,(unsigned long)self.messageList.count);
        
        if (block) {
            if (error) {
                block(error, nil);
            } else {
                if (self.getCarModelType == IMCarTypeCodeR0) {
                    block(nil, message.extra);
                }else if (self.getCarModelType == IMCarTypeCodeOld){
                    if (message.extra) {
                        block(nil, message.extra);
                    } else {
                        uint64_t data = message.body.data;
                        block(nil, [NSData dataWithBytes:&data length:8]);
                    }
                }else if ((self.getCarModelType == IMCarTypeCodeL9)|(self.getCarModelType == IMCarTypeCodeVX)){
                    if (message.para) {
                        block(nil, message.para);
                    } else if (message.para) {
                        block(nil, message.para);
                    } else {
                        block(error, nil);
                    }
                }
            }
        }
        [self dequeueMessage];
    }else { // 收到已过期的莫名回调 - 暂不处理 --- 处理已当超时处理后又收到的回调
        NSString *key = [NSString stringWithFormat:@"%hhu%hhu",message.StandardData.channel,message.StandardData.property];
        NSLog(@"🔥🐶 ========正在处理的key%@ -- 收到的key：%@ 数据%@ -- %@ -- %@ -- %@ ====== %@",self.sendingMessage.key,message.key,message,key,self.carDataKey,message.para,self.carDataBlock);
        if ([key isEqualToString:self.carDataKey] && self.carDataBlock) {
            if (message.para) {
                self.carDataBlock(nil, message.para);
            } else if (message.para) {
                self.carDataBlock(nil, message.para);
            } else {
                self.carDataBlock(error, nil);
            }
        }
    }
    
}

/// 出列
- (void)dequeueMessage {
    if (self.messageQueue == nil) {
        return;
    }
    if (self.timer.isValid) {
        [self.timer invalidate];
        self.timer = nil;
    }

    dispatch_async(self.messageQueue, ^{
        @synchronized(self) {
            if (self.messageList.count > 0 && self.blockList.count > 0) {
                if (self.sendingMessage) {
                    NSLog(@"=======================出列🍰🍰🍰%@",self.sendingMessage.key);
                    [self.messageList removeObject:self.sendingMessage];
                    NSDictionary *blockDic = nil;
                    for (NSDictionary *dic in self.blockList) {
                        IMTCANMessageCompletionBlock block = dic.allValues.firstObject;
                        if (block == self.sendingBlock) {
                            blockDic = dic;
                        }
                    }
                    [self.blockList removeObject:blockDic];
                    self.sendingMessage = nil;
                    self.sendingBlock = nil;
                }
            }
            /// 消息队列延时20毫秒执行  dispatch_async(self.messageQueue, ^{ });
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), self.messageQueue, ^{
                [self checkMessageQueue];
            });
        }
    });
}

#pragma mark - Lazy
- (IMTCANMessageCoder *)messageCoder {
    if (!_messageCoder) {
        _messageCoder = [[IMTCANMessageCoder alloc] init];
    }
    return _messageCoder;
}

- (IMTCANMessageAnalyser *)messageAnalyser {
    if (!_messageAnalyser) {
        _messageAnalyser = [[IMTCANMessageAnalyser alloc] init];
    }
    return _messageAnalyser;
}

- (NSMutableArray *)messageList {
    if (!_messageList) {
        _messageList = [[NSMutableArray alloc] init];
    }
    return _messageList;
}

- (NSMutableArray *)blockList {
    if (!_blockList) {
        _blockList = [NSMutableArray arrayWithCapacity:1];
    }
    return _blockList;
}

- (IM_NewMessageCoder *)newMessageCoder {
    if (!_newMessageCoder) {
        _newMessageCoder = [[IM_NewMessageCoder alloc] init];
    }
    return _newMessageCoder;
}

@end

